package com.easyJava.builder;

import com.easyJava.bean.Constants;
import com.easyJava.bean.FieldInfo;
import com.easyJava.bean.TableInfo;
import com.easyJava.utils.PropertiesUtils;
import com.easyJava.utils.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ZhangYK
 * @version 8.0
 * @title BuildTable
 * @description
 * @create 2024/11/13 22:39
 */
public class BuildTable {
    private static final Logger logger = LoggerFactory.getLogger(BuildTable.class);
    private static Connection conn = null;

    private static String SQL_SHOW_TABLE_STATUS = "show table status";
    private static String SQL_SHOW_FILED = "show full fields from ";

    static {
        String driverName = PropertiesUtils.getString("db.driver");
        String url = PropertiesUtils.getString("db.url");
        String user = PropertiesUtils.getString("db.username");
        String password = PropertiesUtils.getString("db.password");
        try {
            Class.forName(driverName);
            conn = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            logger.error("数据库连接失败", e);
        }
    }

    public static void getTables() {
        PreparedStatement ps = null;
        ResultSet tableResult = null;

        List<TableInfo> tableInfoList = new ArrayList<>();
        try {
            ps = conn.prepareStatement(SQL_SHOW_TABLE_STATUS);
            tableResult = ps.executeQuery();
            while (tableResult.next()){
               String tableName = tableResult.getString("Name");
               String beanName = processField(tableName,true);
               String comment = tableResult.getString("Comment");
               String beanParamName = beanName+ Constants.SUFFIX_BEAN_PARAM;
               //logger.info("表名:{},注释:{},beanName:{},搜索参数bean名:{}",tableName,comment,beanName,beanParamName);

                TableInfo tableInfo = new TableInfo();
                tableInfo.setTableName(tableName);
                tableInfo.setBeanName(beanName);
                tableInfo.setComment(comment);
                tableInfo.setBeanParamName(beanParamName);
                tableInfo.setFieldList(buildFileInfo(tableInfo));

                logger.info(tableInfo.toString());
            }
        } catch (Exception e){
            logger.error("读取表失败",e);
        }finally {
            if (tableResult != null){
                try {
                    tableResult.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (ps != null){
                try {
                    ps.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            if (conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static List<FieldInfo> buildFileInfo(TableInfo tableInfo){
        PreparedStatement ps = null;
        ResultSet rs = null;

        List<FieldInfo> fieldInfoList = new ArrayList<>();

        try{
            ps = conn.prepareStatement(SQL_SHOW_FILED+tableInfo.getTableName());
            rs = ps.executeQuery();
            while (rs.next()){
                String fieldName = rs.getString("Field");
                String sqlType = rs.getString("Type");
                //判断是否自增
                String extra = rs.getString("Extra");
                String comment = rs.getString("Comment");

                FieldInfo fieldInfo = new FieldInfo();
                fieldInfo.setFieldName(fieldName);
                fieldInfo.setPropertyName(processField(fieldName,false));
                if (sqlType.indexOf('(')>0){
                    sqlType = sqlType.substring(0,sqlType.indexOf('('));
                }
                fieldInfo.setSqlType(sqlType);
                fieldInfo.setJavaType(processJavaType(sqlType));
                fieldInfo.setComment(comment);
                if (extra.equals("auto_increment")){
                    fieldInfo.setAutoIncrement(true);
                }


                if (ArrayUtils.contains(Constants.SQL_DATE_TYPES,sqlType)){
                    tableInfo.setHasDate(true);
                }
                if (ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES,sqlType)){
                    tableInfo.setHasDateTime(true);
                }
                if (ArrayUtils.contains(Constants.SQL_DECIMAL_TYPES,sqlType)){
                    tableInfo.setHasBigDecimal(true);
                }

                //logger.info(fieldInfo.toString());
                fieldInfoList.add(fieldInfo);
            }
        }catch (Exception e){
            logger.error("读取字段失败:{}",e);
        }
        return fieldInfoList;
    }

    private static String processJavaType(String sqlType){
        if (ArrayUtils.contains(Constants.SQL_STRING_TYPES,sqlType)){
            return "String";
        }
        if (ArrayUtils.contains(Constants.SQL_LONG_TYPES,sqlType)){
            return "Long";
        }
        if (ArrayUtils.contains(Constants.SQL_INTEGER_TYPES,sqlType)){
            return "Integer";
        }
        if (ArrayUtils.contains(Constants.SQL_DECIMAL_TYPES,sqlType)){
            return "Double";
        }
        if (ArrayUtils.contains(Constants.SQL_DATE_TYPES,sqlType)||ArrayUtils.contains(Constants.SQL_DATE_TIME_TYPES,sqlType)){
            return "Date";
        }

        return "";
    }

    /**
     * 将下划线形式改为驼峰式命名
     * @param field
     * @param upperCaseFirstLatter
     * @return
     */
    private static String processField(String field,Boolean upperCaseFirstLatter){
        StringBuffer sb = new StringBuffer();
        String[] fieldArray = field.split("_");
        if (upperCaseFirstLatter){
            sb.append(StringUtils.upperCaseFirstLatter(fieldArray[0]));
        }else {
            sb.append(fieldArray[0]);
        }
        for (int i = 1; i < fieldArray.length; i++) {
            sb.append(StringUtils.upperCaseFirstLatter(fieldArray[i]));
        }
        return sb.toString();
    }

}
